#include "Subsystems/SubsystemGameInfo.h"
#include "Utils/Utils.h"
#include "ServerConfigure.h"
#include "GameSingleton.h"

namespace PocketSurvival
{
    SubsystemGameInfo::SubsystemGameInfo() :
        environmentBehaviorMode(EnvironmentBehaviorMode::Living),
        timeOfDayMode(TimeOfDayMode::Changing),
        terrainGenerationMode(TerrainGenerationMode::Continent)
    {
        for(int num = 0; num < 16; num++)
        {
            colors.emplace_back();
        }
    }

    void SubsystemGameInfo::update(float dt)
    {
        totalElapsedGameTime += dt;
    }

    void SubsystemGameInfo::load(const nlohmann::json &json)
    {
        ServerConfigure &configure = *(GameSingleton::singletonPtr->getSingleton<ServerConfigure>());
        Utils::GetJsonValue<std::string>(json, worldName, "WorldName", configure.worldDefaultName);
        Utils::GetJsonValue<std::string>(json, originalSerializationVersion, "OriginalSerializationVersion", "2.3");


        gameMode = configure.gameMode;
        environmentBehaviorMode = configure.environmentMode;
        timeOfDayMode = configure.timeOfDayMode;
        recoverFator = configure.recoverFator;
        daySpeed = configure.daySpeed;
        areWeatherEffectsEnabled = configure.areWeatherEffectsEnabled;
        isAdventureRespawnAllowed = configure.isAdventureRespawnAllowed;
        areAdventureSurvivalMechanicsEnabled = configure.areAdventureSurvivalMechanicsEnabled;
        areSupernaturalCreaturesEnabled = configure.areSupernaturalCreaturesEnabled;


        Utils::GetJsonValue<TerrainGenerationMode>(json, terrainGenerationMode, "TerrainGenerationMode", configure.defalutTerrainMode);
        Utils::GetJsonValue<Vector2>(json, islandSize, "IslandSize", configure.defaultIslandSize);
        Utils::GetJsonValue<int32_t>(json, terrainLevel, "TerrainLevel", configure.defaultTerrainLevel);
        Utils::GetJsonValue<float>(json, shoreRoughness, "ShoreRoughness", configure.defaultShoreRoughness);
        Utils::GetJsonValue<int32_t>(json, terrainBlockIndex, "TerrainBlockIndex", configure.defaultTerrainBlockIndex);
        Utils::GetJsonValue<int32_t>(json, terrainOceanBlockIndex, "TerrainOceanBlockIndex", configure.defaultTerrainOceanBlockIndex);
        Utils::GetJsonValue<float>(json, temperatureOffset, "TemperatureOffset", configure.defaultTemperatureOffset);
        Utils::GetJsonValue<float>(json, humidityOffset, "HumidityOffset", configure.defaultsetHumidityOffset);
        Utils::GetJsonValue<int32_t>(json, seaLevelOffset, "SeaLevelOffset", configure.defaultSeaLevelOffset);
        Utils::GetJsonValue<float>(json, biomeSize, "BiomeSize", configure.defaultBiomeSize);
        Utils::GetJsonValue<bool>(json, randomSpawnPosition, "RandomSpawnPosition", false);
        Utils::GetJsonValue<int32_t>(json, worldSeed, "WorldSeed", configure.worldDefaultSeed);
        Utils::GetJsonValue<double>(json, totalElapsedGameTime, "TotalElapsedGameTime", 0.0);
        Utils::GetJsonValue<std::vector<Color3>>(json, colors, "Colors", colors);
    }

    void SubsystemGameInfo::save(nlohmann::json &json)
    {
        json["WorldName"]                           = worldName;
        json["OriginalSerializationVersion"]        = originalSerializationVersion;

        json["GameMode"]                            = gameMode;

        json["EnvironmentBehaviorMode"]             = environmentBehaviorMode;
        json["TimeOfDayMode"]                       = timeOfDayMode;
        json["RecoverFator"]                        = recoverFator;
        json["DaySpeed"]                            = daySpeed;
        json["AreWeatherEffectsEnabled"]            = areWeatherEffectsEnabled;
        json["IsAdventureRespawnAllowed"]           = isAdventureRespawnAllowed;
        json["AreAdventureSurvivalMechanicsEnabled"]= areAdventureSurvivalMechanicsEnabled;
        json["AreSupernaturalCreaturesEnabled"]     = areSupernaturalCreaturesEnabled;
        json["IslandSize"]                          = islandSize;
        json["TerrainLevel"]                        = terrainLevel;
        json["ShoreRoughness"]                      = shoreRoughness;
        json["TerrainBlockIndex"]                   = terrainBlockIndex;
        json["TerrainOceanBlockIndex"]              = terrainOceanBlockIndex;
        json["TemperatureOffset"]                   = temperatureOffset;
        json["HumidityOffset"]                      = humidityOffset;
        json["SeaLevelOffset"]                      = seaLevelOffset;
        json["BiomeSize"]                           = biomeSize;
        json["RandomSpawnPosition"]                 = randomSpawnPosition;
        json["WorldSeed"]                           = worldSeed;
        json["TotalElapsedGameTime"]                = totalElapsedGameTime;
        json["Colors"]                              = colors;
    }

    void SubsystemGameInfo::saveToMsgJson(nlohmann::json &jsonData)
    {
        MSG_VALUE_SET(jsonData, "WorldName", "string", worldName);
        MSG_VALUE_SET(jsonData, "OriginalSerializationVersion", "string", originalSerializationVersion);
        MSG_VALUE_SET(jsonData, "GameMode", "Game.GameMode", GameModeStr[(uint8_t)gameMode]);
        MSG_VALUE_SET(jsonData, "EnvironmentBehaviorMode", "Game.EnvironmentBehaviorMode", EnvironmentBehaviorModeStr[(int8_t)environmentBehaviorMode]);
        MSG_VALUE_SET(jsonData, "TimeOfDayMode", "Game.TimeOfDayMode", TimeOfDayModeStr[(int8_t)timeOfDayMode]);
        MSG_VALUE_SET(jsonData, "RecoverFator", "float", recoverFator);
        MSG_VALUE_SET(jsonData, "DaySpeed", "float", daySpeed);
        MSG_VALUE_SET(jsonData, "AreWeatherEffectsEnabled", "bool", areWeatherEffectsEnabled);
        MSG_VALUE_SET(jsonData, "IsAdventureRespawnAllowed", "bool", isAdventureRespawnAllowed);
        MSG_VALUE_SET(jsonData, "AreAdventureSurvivalMechanicsEnabled", "bool", areAdventureSurvivalMechanicsEnabled);
        MSG_VALUE_SET(jsonData, "AreSupernaturalCreaturesEnabled", "bool", areSupernaturalCreaturesEnabled);
        MSG_VALUE_SET(jsonData, "TerrainGenerationMode", "Game.TerrainGenerationMode", TerrainGenerationModeStr[(int8_t)terrainGenerationMode]);
        MSG_VALUE_SET(jsonData, "IslandSize", "Vector2", islandSize.toString());
        MSG_VALUE_SET(jsonData, "TerrainLevel", "int", terrainLevel);
        MSG_VALUE_SET(jsonData, "ShoreRoughness", "float", shoreRoughness);
        MSG_VALUE_SET(jsonData, "TerrainBlockIndex", "int", terrainBlockIndex);
        MSG_VALUE_SET(jsonData, "TerrainOceanBlockIndex", "int", terrainOceanBlockIndex);
        MSG_VALUE_SET(jsonData, "TemperatureOffset", "float", temperatureOffset);
        MSG_VALUE_SET(jsonData, "HumidityOffset", "float", humidityOffset);
        MSG_VALUE_SET(jsonData, "SeaLevelOffset", "int", seaLevelOffset);
        MSG_VALUE_SET(jsonData, "BiomeSize", "float", biomeSize);
        MSG_VALUE_SET(jsonData, "RandomSpawnPosition", "bool", randomSpawnPosition);
        MSG_VALUE_SET(jsonData, "WorldSeed", "int", worldSeed);
        MSG_VALUE_SET(jsonData, "TotalElapsedGameTime", "double", totalElapsedGameTime);
        
        nlohmann::json palette;

        MSG_VALUE_SET(palette, "Colors", "string", ";;;;;;;;;;;;;;;");
        MSG_VALUE_SET(palette, "Names", "string", "白色;浅青色;粉红色;浅蓝色;黄色;浅绿色;鲑鱼红色;亮灰色;灰色;青色;紫色;蓝色;棕色;绿色;红色;黑色");

        jsonData["Palette"] = palette;
    }

    static const std::string subsystemName = "GameInfo";
    const std::string& SubsystemGameInfo::getName() const
    {
        return subsystemName;
    }
    SubUpdateType SubsystemGameInfo::getUpdateType()
    {
        return SubUpdateType::MultiThreadUpdate;
    }
}